
#include "OpenGL.hpp"
#include "TestEngine.hpp"
#include "Animator.hpp"
#include "Vector3.hpp"
#include "Aspect.hpp"
#include "Camera.hpp"
#include "MathHelper.hpp"
#include <time.h>

class Player : public GameComponent<Player> {
	Vector3 pos;
};

void TestEngine::Initialize() {

	texture.LoadFromPng("D:/Jeppes/Jeppe.png");

	camera.AddComponent<Transform>()->Position = Vector3(5,7,10);
	camera.AddComponent<Hierarchy>();
	Camera* cam = camera.AddComponent<Camera>();
	
	cam->FieldOfView = 60;
	cam->Aspect = System->ScreenSize.right / System->ScreenSize.bottom;
	

	//mesh.AddQuad(0,5, Colour::Green(0.5f));

	mesh.AddCube(0, 1, Colour::Green(0.5f));

	transformRotator.SetInputManager(&InputManager);
	transformRotator.AddComponent<Camera>();

	transformMover.SetInputManager(&InputManager);
	transformMover.AddComponent<Camera>();

	world.AddSystem(&transformHierarchy);
	world.AddSystem(&renderer);
	world.AddSystem(&transformRotator);
	world.AddSystem(&transformMover);
	world.AddSystem(&physics);

	world.AddGameObject(&camera);


	for (int y=0; y<10; y++) {
		for(int x=0; x<((y & 1) ? 4 : 5); x++) {
			GameObject* cube = CreatePhysicsCube(Vector3(x*2.5f+((y & 1) ? 1.25f : 0),1+y*2.005f,-10));
			world.AddGameObject(cube);
		}
	}


	btCollisionShape* groundShape = new btBoxShape(btVector3(100,0.1f,100));
	btRigidBody::btRigidBodyConstructionInfo* groundDefinition = new btRigidBody::btRigidBodyConstructionInfo(0,0,groundShape,btVector3(0,0,0));

	GameObject* ground = new GameObject();
	ground->AddComponent<Transform>()->Position = Vector3(0,0,0);
	ground->AddComponent<RigidBody>()->Body = groundDefinition;

	world.AddGameObject(ground);

	GameObject* light = new GameObject();

	light->AddComponent<Light>();
	light->AddComponent<Transform>();
	light->AddComponent<Hierarchy>()->Parent = &camera;
	light->GetComponent<Transform>()->Position = Vector3(0,0,-10);

	world.AddGameObject(light);

	GameObject* li = CreateCube(light->GetComponent<Transform>()->Position);
	li->GetComponent<Hierarchy>()->Parent = &camera;

	world.AddGameObject(li);

	/*
	sub = CreateCube(Vector3(0,0,5));
	sub->GetComponent<Hierarchy>()->Parent = rotator;

	GameObject* subSub = CreateCube(Vector3(0,3,0));
	subSub->GetComponent<Hierarchy>()->Parent = sub;
	*/

	//CreateCube(Vector3(-6,0,-10))->GetComponent<Transform>()->Matrix = Matrix4x4::CreateScale(Vector3(1,1.5f,1));



	//camera.GetComponent<Hierarchy>()->Parent = player;
	//camera.GetComponent<Transform>()->Position = Vector3(0,4,10);
	//camera.GetComponent<Transform>()->Rotation = Quaternion::Create(ToRadians(-20), Vector3(1,0,0));


	InputManager.Down +=event_handler(this, &TestEngine::Click);
}

static long lastTime = 0;

void TestEngine::Click(InputManager::EventData event) {
	if (event.Index !=0) return;

	long time = clock();

	long delta = time - lastTime;
	lastTime = time;

	if (delta>300) return;


	Vector3 position = camera.GetComponent<Transform>()->World.GetValue()->TransformPosition(Vector3(0,0,0));

	GameObject* go = CreatePhysicsCube(position);
	world.AddGameObject(go);

	go->GetComponent<RigidBody>()->ApplyImpulse(camera.GetComponent<Transform>()->World.GetValue()->TransformVector(Vector3(0,0,-50)), 0);

}

static float rotation = 0;

void TestEngine::Update(float dt) {

	rotation+=dt;
	
	Vector3 vec(1,0.5f,0);
	vec.Normalize();

	//rotator->GetComponent<Transform>()->Rotation = Quaternion::Create(rotation, vec);
	//sub->GetComponent<Transform>()->Position = Vector3(0,0,5+sinf(rotation) * 5);

	//sub->GetComponent<Transform>()->Rotation = Quaternion::Create(rotation, Vector3(0,1,0));

	//sprite.GetComponent<Transform>()->Position = Vector3(0,0, -InputManager.GetPosition(0).x);
	
	physics.Update(dt);

	transformRotator.Update(dt);
	transformMover.Update(dt);

	//camera.Rotation = Quaternion::Create(rotation * 2, Vector3(0,1,0));
}

GameObject* TestEngine::CreateCube(Vector3 position) {
	GameObject* go = new GameObject();

	go->AddComponent<Hierarchy>();
	go->AddComponent<Transform>()->Position = position;
	go->AddComponent<Renderable>()->Mesh = &mesh;
	go->GetComponent<Renderable>()->Texture = &texture;


	return go;
}

GameObject* TestEngine::CreatePhysicsCube(Vector3 position) {
	GameObject* go = CreateCube(position);

	btCollisionShape* boxShape = new btBoxShape(btVector3(1,1,1));
	boxShape->calculateLocalInertia(1,btVector3(1,1,1));

	btRigidBody::btRigidBodyConstructionInfo* info = new btRigidBody::btRigidBodyConstructionInfo(1,0,boxShape,btVector3(1,1,1));

	go->AddComponent<RigidBody>()->Body = info;
	
	return go;
}




void TestEngine::Render() {
	glClearColor(0,0,0,1);
	glClear(GL_COLOR_BUFFER_BIT);

	//camera.GetComponent<Transform>()->Position = Vector3(0,InputManager.GetPosition(0).y*0.01f,InputManager.GetPosition(0).x*0.01f);
	
	

	renderer.Render(&camera, System->ScreenSize);





}